package cn.net.lwj.singledb.service.impl;

import cn.net.lwj.common.service.Impl.BaseServiceImpl;
import cn.net.lwj.common.util.CreateNewKey;
import cn.net.lwj.singledb.service.TXfTaskService;
import cn.net.lwj.singledb.service.TransactionalService;
import generate.entity.TSjjhLog;
import generate.entity.TXfBljdqk;
import generate.entity.TXfTask;
import generate.mapper.TSjjhLogMapper;
import generate.mapper.TXfBljdqkMapper;
import generate.mapper.TXfTaskMapper;
import java.util.Date;
import java.util.List;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

/**
 * 测试事务  类上无事务注解
 */
@Service
@Slf4j
public class TransactionalServiceImpl extends BaseServiceImpl implements TransactionalService {


    @Resource
    private TSjjhLogMapper sjjhLogMapper;
    @Resource
    private TXfBljdqkMapper bljdqkMapper;
    @Resource
    private TXfTaskMapper taskMapper;
    @Resource
    private TXfTaskService taskService;

    @Resource
    private DemoServiceImpl demoService;

    @Resource
    private TransactionalServiceImpl transactionalService;

    @Autowired
    private SqlSessionTemplate sqlSessionTemplate;
    /**
     * 测试无事务行为
     */
    public void testNoTx(){
        //List<Map<String, Object>> list = sqlSessionTemplate.getMapper(TreeMapper.class).getQgfyTree("");
        //System.out.println(list);
        TXfTask task = new TXfTask("1", "1", 1004);
        taskService.saveOrUpdate(task);
        "".substring(5);
        //taskMapper.select();
        List<TXfTask> list = taskService.list();
        TXfBljdqk bljdqk = new TXfBljdqk("1", 1006, "", "", new Date());
        bljdqkMapper.insert(bljdqk);
        //如果此处抛出异常，上面的保存不会回滚,类或者方法上有事务注解则被回滚
        "".substring(5);
        System.out.println(list);
        log.info("222222222");
    }
    /**
     * 测试单方法有事务
     * 捕获异常时事务失效；
     * 设置手动回滚后，事务生效
     */
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
    public void testTx(){
        try {
            TXfTask task = new TXfTask("1", "1", 1004);
            taskService.saveOrUpdate(task);
            "".substring(5);
            //taskMapper.select();
            List<TXfTask> list = taskService.list();
            TXfBljdqk bljdqk = new TXfBljdqk("1", 1006, "", "", new Date());
            bljdqkMapper.insert(bljdqk);
            //如果此处抛出异常，上面的保存不会回滚,类或者方法上有事务注解则被回滚
            "".substring(5);
            System.out.println(list);
            log.info("222222222");
        } catch (Exception e) {
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
    }

    /**
     * 测试事务  主方法上加事务
     *
     * 情形一：捕获异常且不手动回滚，事务失效，如果保存日志成功，那么前面所有成功的操作都被提交，
     * 保存日志失败（saveLog(sjjhLog);），则所有都失败(相当于在外层抛出了异常）
     * 情形二：捕获异常且手动回滚（setRollbackOnly）,保存日志不独立事务(saveLog):异常后日志也不能成功
     * 情形三：捕获异常且手动回滚（setRollbackOnly）,保存日志独立事务(saveLogTxNew):异常后日志也不能成功
     * 情形四：捕获异常后抛出异常：回滚，事务生效，同样最外层日志也没保存成功！
     * 情形五：嵌套try catch，内嵌套里面异常，内嵌套外无异常:三张表全保存成功，内嵌套的异常被捕获
     * 情形六：嵌套try catch，内嵌套里面异常且手动在内嵌套回滚，内嵌套外无异常:三张表全回滚,事务生效，日志也没保存成功！
     * 情形七：嵌套try catch，内嵌套里面异常且手动在内嵌套回滚，内嵌套外无异常->
     * a:保存日志用另一个类的新事务方法:新事务生效，日志保存成功，其他则被回滚
     * b:保存日志用另一个类的Propagation.REQUIRED方法，三张表全部被回滚。
     * c:保存日志用注入的本类（注入自己）的 REQUIRES_NEW方法，新事务生效，日志保存成功，其他则被回滚
     *
     *
     * 综上：在同一类独立事务的保存日志是失效的！！！
     */
    //@Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = false)
    //@Transactional(propagation = Propagation.REQUIRED, readOnly=true)
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
    public void testMainHasTx(){
        //JhlogPk jhlogPk = new JhlogPk("111", "111", 1001, "111");
        TSjjhLog sjjhLog = new TSjjhLog(CreateNewKey.createId(), "111", 1001, "111", 2950, "111.zip");
        try {
            TXfTask task = new TXfTask("1", "1", 1004);
            taskService.saveOrUpdate(task);
            log.info("保存任务表000");
            List<TXfTask> list = taskService.list();

            try {
                TXfBljdqk bljdqk = new TXfBljdqk("2", 1006, "", "", new Date());
                //saveBljdqk(bljdqk);
                saveBljdqkTxNew(bljdqk);
                log.info("保存办理进度情况表。。。");
                "".substring(5);
            } catch (Exception ee) {
                ee.printStackTrace();
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                //TransactionAspectSupport.currentTransactionStatus().isRollbackOnly();
            }
            //TXfBljdqk bljdqk = new TXfBljdqk("2", 1006, "", "", new Date());
            ////saveBljdqk(bljdqk);
            //saveBljdqkTxNew(bljdqk);
            //log.info("保存办理进度情况表。。。");
            //如果此处抛出异常，上面的保存不会回滚,类或者方法上有事务注解则被回滚
            //"".substring(5);
            System.out.println(list);
            log.info("222222222");
            sjjhLog.setnStatus(200);
            sjjhLog.setcException(null);
        } catch (Exception e) {
            e.printStackTrace();
            sjjhLog.setcException(e.getMessage());
            sjjhLog.setnStatus(500);
            //TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            throw new RuntimeException("处理失败");
        }finally {
            //saveLog(sjjhLog);
            //saveLogTxNew(sjjhLog);
            //demoService.saveLogTxNew(sjjhLog);
            //demoService.saveLogTx(sjjhLog);
            transactionalService.saveLogTxNew(sjjhLog);
        }
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
    public void saveLogTxNew(TSjjhLog log) {
        sjjhLogMapper.insert(log);
    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
    public void saveLogTx(TSjjhLog log) {
        sjjhLogMapper.insert(log);
    }

    public void saveLog(TSjjhLog log) {
        sjjhLogMapper.insert(log);
    }


    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
    public void saveBljdqkTxNew(TXfBljdqk bljdqk) {
        bljdqkMapper.insert(bljdqk);
    }
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
    public void saveBljdqkTx(TXfBljdqk bljdqk) {
        bljdqkMapper.insert(bljdqk);
    }
    public void saveBljdqk(TXfBljdqk bljdqk) {
        bljdqkMapper.insert(bljdqk);
    }

}
